/**
 * ParamSignAuthInterceptor.java 
 * Copyright © 2014-2016, 杭州泊享网络科技有限公司
 * 
 * @author Liu Tao
 * @create 2015年5月22日
 */
package com.pshare.framework.interceptor;

import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.TreeMap;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import com.pshare.constant.SeaxConstants;
import com.pshare.framework.exception.WrongSignException;
import com.pshare.tool.SessionTool;
import com.pshare.util.EncodeUtils;
import com.pshare.util.StringUtils;
import com.pshare.util.SysPropertyUtils;

/**
 * 签名验证
 * 对所有参数组成的字符串做MD5校验
 * 不需要全部接口都用
 */
public class ParamSignAuthInterceptor extends HandlerInterceptorAdapter {

	private static final Logger logger = Logger.getLogger(ParamSignAuthInterceptor.class);
	private static final String SIGN_CHECK = SysPropertyUtils.getProperty("sys.signcheck");

	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
		logger.debug("ParamSignAuthInterceptor.preHandler...");
		
		// 校验开关
		if ("0".equals(SIGN_CHECK)) {
			return true;
		}
		
		// POST PUT请求的json格式数据在表单做验证
		// 签名验证暂时这么处理，后面有时间再做调整
		final String method = request.getMethod();
		if ("POST".equalsIgnoreCase(method) || "PUT".equalsIgnoreCase(method)) {
			if ("application/json".equalsIgnoreCase(request.getContentType())) {
				return true;
			}
		}
		
		String paramSign = request.getHeader(SeaxConstants.KEY_SIGN_DATA);
		if (StringUtils.isBlank(paramSign)) {
			throw new WrongSignException();
		}
		
		String generatedSign = generateSign(request, SessionTool.getUserId());
		if (!paramSign.equals(generatedSign)) {
			throw new WrongSignException();
		}

		return true;
	}

	private String generateSign(HttpServletRequest request, Long userId) {
		String uid = userId == null ? SeaxConstants.VALUE_DEFAULT_USER_ID : userId + SeaxConstants.EMPTY;

		Map<String, String> map = sortParams(request, SeaxConstants.KEY_SIGN_DATA);
		map.put("uid", uid);

		StringBuilder str = new StringBuilder();
		for (String key : map.keySet()) {
			str.append(key).append(map.get(key));
		}
		
		String calculatedSign = EncodeUtils.encodeByMD5(str.toString());
		return calculatedSign;
	}

	private Map<String, String> sortParams(HttpServletRequest request, String... except) {
		// 参数Map
		Map<String, String[]> parameters = request.getParameterMap();
		// 返回值Map
		Map<String, String> map = new TreeMap<String, String>();
		Iterator<Entry<String, String[]>> entries = parameters.entrySet().iterator();
		Map.Entry<String, ?> entry;
		String name = "";
		String value = "";
		while (entries.hasNext()) {
			boolean isObject = true;
			entry = (Map.Entry<String, ?>) entries.next();
			name = (String) entry.getKey();
			for (String s : except) {
				if (s.equals(name)) {
					isObject = false;
					break;
				}
			}
			if (isObject) {
				Object valueObj = entry.getValue();
				if (null == valueObj) {
					value = "";
				} else if (valueObj instanceof String[]) {
					String[] values = (String[]) valueObj;
					for (int i = 0; i < values.length; i++) {
						value = StringUtils.trimToEmpty(values[i]) + ",";
					}
					int len = value.length();
					if (len > 0) {
						value = value.substring(0, len - 1);
					}
				} else {
					value = StringUtils.trimToEmpty(valueObj);
				}
				map.put(name, value);
			}
		}

		return map;
	}

}
